<?php

namespace app\common\model\xilumarket;

use app\admin\model\xilumarket\order\OrderDelivery;
use app\common\library\Auth;
use app\common\model\User;
use app\common\model\xilumarket\User as XilumarketUser;
use think\Db;
use think\Exception;
use think\exception\PDOException;
use think\Hook;
use think\Model;
use function fast\array_get;


class Order extends Model
{
    

    // 表名
    protected $name = 'xilumarket_order';
    
    // 自动写入时间戳字段
    protected $autoWriteTimestamp = 'int';

    // 定义时间戳字段名
    protected $createTime = 'createtime';
    protected $updateTime = 'updatetime';
    protected $deleteTime = false;

    const ORDER_TYPE_FREIGHT = 1; //物流
    const ORDER_TYPE_SELF = 2; //自提
    const ORDER_TYPE_DELEVERY = 3; //配送

    // 追加属性
    protected $append = [
        'state',
        'state_text',
        'expiretime_text'
    ];

    const ORDER_STATUS = [
        '-1'=>'已取消',
        '0'=>'待支付',
        '1'=>'待发货',
        '2'=>'待收货',
        '3'=>'待评价',
        '4'=>'已完成',
        '5'=>'退款申请中',
        '6'=>'已退款',
        '7'=>'退款失败',
    ];

    //状态对应文本消息
    public function getStateTextAttr($value, $data)
    {
        $state = $this->getAttr('state');
        return isset($state) ? self::ORDER_STATUS[$state] :'';
    }

    /**
     * 获取对订单状态
     */
    public function getStateAttr($value, $data)
    {
        if(!isset($data['order_status'])){
            return '';
        }
        else if ($data['order_status'] == '3') {
            //已完成
//            if($data['refund_status'] == '3'){
//                $state = '7'; //退款失败
//            }else
                if($data['refund_status'] == '2'){
                $state = '6';//退款成功
            }else if($data['refund_status'] == '1'){
                $state = '5';//退款中
            }else{
                $state = '4'; //已完成
            }
        }
        else if ($data['order_status'] == '2') {
            //取消
            $state = '-1';
        }
        else {
            //进行中
            if ($data['pay_status'] == '1') {
//                if($data['refund_status'] == '3'){
//                    $state = '7'; //退款失败
//                }else
                if($data['refund_status'] == '2'){
                    $state = '6';//退款成功
                }else if($data['refund_status'] == '1'){
                    $state = '5';//退款中
                } else if ($data['freight_status'] == '1') {
                    //已发货
                    if ($data['receipt_status'] == '1') {
                        //已收货
                        if ($data['comment_status'] == '1') {
                            $state = '4';
                        }
                        else {
                            $state = '3';
                        }
                    }
                    else {
                        //待收货
                        $state = '2';
                    }
                }
                else {
                    //待发货
                    $state = '1';
                }
            }
            else {
                //待付款
                $state = '0';
            }
        }
        return $state;
    }

    /**
     * 订单过期时间
     * @return int;
     */
    public static function getExpiretime(){
        $shopinfo = Config::getMyConfig('shopinfo');
        $auto_close_minutes = !empty($shopinfo['auto_close_minutes']) ? $shopinfo['auto_close_minutes'] : 15;
        return time()+bcmul($auto_close_minutes,60);
    }

    public function getExpiretimeTextAttr($value,$data){
        $value = $value ? $value : (isset($data['expiretime']) ? $data['expiretime'] : '');
        return is_numeric($value) ? date("m.d H:i", $value) : $value;
    }

    public function getFreightTypeList()
    {
        return ['1' => __('Freight_type 1'), '2' => __('Freight_type 2'), '3' => __('Freight_type 3')];
    }

    public function getPayStatusList()
    {
        return ['0' => __('Pay_status 0'), '1' => __('Pay_status 1')];
    }

    public function getFreightStatusList()
    {
        return ['0' => __('Freight_status 0'), '1' => __('Freight_status 1')];
    }

    public function getReceiptStatusList()
    {
        return ['0' => __('Receipt_status 0'), '1' => __('Receipt_status 1')];
    }

    public function getOrderStatusList()
    {
        return ['1' => __('Order_status 1'), '2' => __('Order_status 2'), '3' => __('Order_status 3')];
    }


    public function getFreightTypeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['freight_type']) ? $data['freight_type'] : '');
        $list = $this->getFreightTypeList();
        return isset($list[$value]) ? $list[$value] : '';
    }

    public function getPaytimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['paytime']) ? $data['paytime'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getFreighttimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['freighttime']) ? $data['freighttime'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }


    public function getReceipttimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['receipttime']) ? $data['receipttime'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    public function getCommenttimeTextAttr($value, $data)
    {
        $value = $value ? $value : (isset($data['commenttime']) ? $data['commenttime'] : '');
        return is_numeric($value) ? date("Y-m-d H:i:s", $value) : $value;
    }

    /**
     * 订单用户
     */
    public function user(){
        return $this->belongsTo(User::class,'user_id','id',[],'LEFT')->setEagerlyType(0);
    }
    /**
     * 订单用户
     */
    public function seller(){
        return $this->belongsTo(User::class,'seller_user_id','id',[],'LEFT')->setEagerlyType(0);
    }
    /**
     * 订单商品
     */
    public function orderProduct(){
        return $this->hasMany(OrderProduct::class,'order_id','id');
    }
    /**
     * 订单地址
     */
    public function orderAddress(){
        return $this->hasOne(OrderAddress::class,'order_id','id',[],'LEFT')->setEagerlyType(0);
    }

    /**
     * 条件
     */
    public static function orderWhere($state){
        switch ($state){
            case -1:
                //取消
                $where['order_status'] = '2';
                $order = 'canceltime desc';
                break;
            case 1:
                //待支付
                $where['pay_status'] = '0';
                $where['freight_status'] = '0';
                $where['receipt_status'] = '0';
                $where['order_status'] = '1';
                $order = 'createtime desc';
                break;
            case 2:
                //待发货
                $where['pay_status'] = '1';
                $where['freight_status'] = '0';
                $where['receipt_status'] = '0';
                $where['order_status'] = '1';
                $order = 'paytime desc';
                break;
            case 3:
                //待收货
                $where['pay_status'] = '1';
                $where['freight_status'] = '1';
                $where['receipt_status'] = '0';
                $where['order_status'] = '1';
                $order = 'freighttime desc';
                break;
            case 4:
                //待评价
                $where['pay_status'] = '1';
                $where['freight_status'] = '1';
                $where['receipt_status'] = '1';
                $where['comment_status'] = '0';
                $where['order_status'] = '1';
                $order = 'receipttime desc';
                break;
            case 5:
                //已完成
                $where['pay_status'] = '1';
                $where['freight_status'] = '1';
                $where['receipt_status'] = '1';
                //$where['comment_status'] = '1';
                $where['order_status'] = '3';
                $order = 'commenttime desc';
                break;
            case 6:
                //售后
                $where['pay_status'] = '1';
                $where['refund_status'] = '1';
                $order = 'refund_time desc';
                break;
            default:
                //全部
                $where = [];
                $order = 'id desc';
                break;
        }

        return [$where,$order];

    }

    /**
     * 订单确认
     */
    public static function sure($params,$user_id){

        $ids = array_get($params,'ids');
        if(!$ids){
            throw new Exception('下单参数错误');
        }
        #2.获取商品信息
        $rows = Product::getProduct($ids);
        // var_dump($rows);die;
        if(!$rows){
            throw new Exception('请选择要下单商品');
        }
        

        #1.1循环获取总价格
        $pay_price = $total_price = 0;
        $freight_type = array_get($params,'freight_status', null) ??$rows[0]['freight_status'];
        // var_dump($freight_type);die;
        $freight_goods = [];
        $order_type = $freight_type == 3 ? self::ORDER_TYPE_SELF : ($freight_type == 4 ? self::ORDER_TYPE_DELEVERY : self::ORDER_TYPE_FREIGHT);//默认物流
        
        $config = \app\common\model\Config::get(['name' => 'delivery_fee']);
        $freight_price =  $order_type == self::ORDER_TYPE_DELEVERY ? $config['value'] : $rows[0]['freight_money'];

        #1.收货地址
        $address = null;
        if($order_type != self::ORDER_TYPE_SELF){
            $address = UserAddress::get_order_address($user_id,array_get($params,'address_id'));
        }

        foreach ($rows as $row) {
            if($row['sale_out_status'] == 1){
                throw new Exception("商品已被下单");
            }
            if($row['sale_out_status'] == 2){
                throw new Exception("商品已售出");
            }
            if($user_id == $row['user_id']){
                throw new Exception("自己不可购买");
            }
            //物流自提
            // $order_type = ;
            #单品总价,根据有无规格选择不同商品价格
            $row['amount'] = $row['salesprice'];
            // 配送时，如果非同城，则不能购买
            if(array_get($params,'address_id') 
                && $freight_type == self::ORDER_TYPE_DELEVERY &&
                !($row['province_id'] == $address->province_id && $row->city_id == $address->city_id && $row->region_id == $address->region_id)) {
                throw new Exception('该地址超出配送范围');
            }

            $total_price = bcadd($total_price,$row['amount'],2);

            $pay_price = bcadd($pay_price,$row['amount'],2);
            $freight_goods[] = $row;
        }
        unset($row);
        if($freight_goods && $pay_price < 0.01){
            throw new Exception("商品金额错误");
        }
        //运费
        $pay_price = bcadd($pay_price,$freight_price,2);


        return [
            'order_type'    => $order_type, //1=物流，2=自提，3=配送
            'address'       => $address,
            'productList'   => $freight_goods, //商品
            'total_price'   => (string)$total_price, // 总金额
            'pay_price'     => (string)$pay_price, // 总金额
            'freight_price' => (string)$freight_price, // 运费
            'total'         => 1,// 总件数
            'freight_type'  =>  $freight_type
        ];
    }
    /**
     * 下单
     */
    public static function create_order($params,$userId){
        $sure = self::sure($params,$userId);
        // var_dump($sure);
        if($sure['order_type']!=self::ORDER_TYPE_SELF && !$address_id = array_get($params,'address_id')){
            throw new Exception('收货地址不得为空');
        }
        $expiretime = self::getExpiretime();
        //生成订单
        Db::startTrans();
        try {
            $config = \app\common\model\Config::get(['name' => 'delivery_fee']);
            // var_dump($config);
            $order = self::create([
                'order_type'    => $sure['order_type'],
                'platform'      => array_get($params,'platform','wxmini'),
                'order_no'      =>  'A'.date('YmdHis').mt_rand(0,9999),
                'user_id'       =>  $userId,
                'seller_user_id'=>  $sure['productList'][0]['user_id'],
                'total_price'   =>  $sure['total_price'],
                'pay_price'     =>  $sure['pay_price'],
                'express_price' =>  $sure['order_type'] == self::ORDER_TYPE_DELEVERY ? $config['value'] : $sure['freight_price'] ?? 0,
                'freight_type'  =>  $sure['freight_type'] ?? 0,
                'remarks'       =>  $sure['remarks'] ?? '',
                'expiretime'    =>  $expiretime,
                'order_ip'      =>  request()->ip()
            ]);
            //自提不需要物流
            if($sure['order_type'] != self::ORDER_TYPE_SELF){
                $address = $sure['address'];
                //订单收货信息
                OrderAddress::create([
                    'user_id'       => $userId,
                    'order_id'      => $order->id,
                    'name'          => $address['name'],
                    'mobile'        => $address['mobile'],
                    'province_id'   => $address['province_id'],
                    'city_id'       => $address['city_id'],
                    'region_id'     => $address['region_id'],
                    'address_detail'=> $address['address'],
                ]);
            }
            foreach ($sure['productList'] as $v){
                $order_goods['order_id'] = $order->id;
                $order_goods['product_id'] = $v['id'];
                $order_goods['category_id'] = $v['category_id'];
                $order_goods['product_name'] = $v['name'];
                $order_goods['image']  = $v['thumb_image_text'];
                $order_goods['product_price'] = $v['salesprice'];
                $order_goods['market_price']  = $v['line_price'];
                $order_goods['sum_price'] = $v['amount'];
                $order_goods['total_num'] = 1;
                OrderProduct::create($order_goods);
                $product = Product::find($v['id']);
                //商品状态变成已售出
                if($product->number == 1){
                    Product::where('id',$v['id'])->dec('number')->update(['sale_out_status'=>2]);
                }else{
                    Product::where('id',$v['id'])->setDec('number');
                }
            }
        }catch (PDOException|Exception $e){
            Db::rollback();
            throw $e;
        }
        Db::commit();
        return self::get($order->id);
    }

    /**
     * 订单数量
     * @param $where
     * @return int|string
     * @throws \think\Exception
     */
    public static function get_count($where){
        return self::where($where)->count();
    }


    /**
     * 订单列表
     * @param array $param
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public static function orderList($param,$userId){
        $state = !empty($param['state']) ? $param['state'] : 999;
        list($where,$order) = self::orderWhere($state);
        $where['user_id'] = $userId;
        $limit = $param['pagesize'] ?? 10;
        $list = self::field("id,order_type,user_id,order_no,pay_type,total_price,pay_price,express_price,freight_type,express_name,express_code,express_no,pay_status,expiretime,freight_status,receipt_status,comment_status,refund_status,order_status,createtime")
            ->with(['seller'=>function($query){
                $query->withField(['id','nickname','avatar']);
            },
            'orderProduct'=>function($query){
                $query->field(['id','order_id','product_id','product_name','image','product_price','sum_price']);
            },
            ])
            ->where($where)
            ->order($order)
            ->paginate($limit);
        return $list;
    }

    /**
     * 订单详情
     */
    public static function order_detail($param){
        $row = self::get($param['order_id'],['orderProduct','orderAddress','seller'=>function($q){
            $q->withField(['id','nickname','avatar']);
        }, 'deliveryuser' => ['user']]);
        if($row){
            $row->setAttr("aftersale",Aftersale::where('order_id',$row->id)->order('id','desc')->find());
        }
        return $row;
    }

    /**
     * 确认收货
     * @param array $param
     * @return Object
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    public static function receive($param)
    {
        $row = self::get($param['order_id']);
        if(!$row || $row->user_id != (Auth::instance())->id){
            throw new Exception("订单不存在或没有权限操作");
        }
        if($row->state != '2'){
            throw new Exception("订单当前状态不可操作");
        }
        $row->receipt_status = '1';
        $row->receipttime = time();
        $row->save();
        //确认收货，提醒卖家
        Hook::listen('xilumarket_order_finish',$row);
        return $row;
    }

    /**
     * 取消订单
     */
    public static function cancel($params = NULL)
    {
        $row = self::get($params['order_id']);

        if(!$row || $row->user_id != (Auth::instance())->id){
            throw new Exception("订单不存在或没有权限操作");
        }

        if($row->state != '0'){
            throw new Exception("订单当前状态不可操作");
        }
        $row->order_status = '2';
        $row->canceltime = time();
        $row->save();
        //同时修改商品的售出状态
        foreach ($row->order_product as $product){
            Product::where('id',$product->product_id)->update(['sale_out_status'=>0]);
        }
        return $row;
    }


    /**
     * 卖家订单列表
     * @param array $param
     * @return \think\Paginator
     * @throws \think\exception\DbException
     */
    public static function saleLists($params,$userId)
    {
        $state = !empty($params['state']) ? $params['state'] : 0;
        list($where,$order) = self::orderWhere($state);
        $limit = $param['pagesize'] ?? 10;
        $list = self::field("id,order_type,user_id,order_no,pay_type,total_price,pay_price,express_price,freight_type,express_name,express_code,express_no,pay_status,freight_status,expiretime,receipt_status,comment_status,refund_status,order_status,createtime")
            ->with(['user'=>function($query){
                $query->withField(['id','nickname','avatar']);
            },
                'orderProduct'=>function($query){
                $query->field(['id','order_id','product_name','image','product_price','sum_price']);
                }])
            ->where($where)
            ->where('seller_user_id', $userId)
            ->order($order)
            ->paginate($limit);
        return $list;
    }

    /**
     * 订单详情
     */
    public static function sellerDetail($param){
        $row = self::get($param['order_id'],['orderProduct','orderAddress','user'=>function($q){
            $q->withField(['id','nickname','avatar']);
        }]);
        if($row){
            $row->setAttr("aftersale",Aftersale::where('order_id',$row->id)->order('id','desc')->find());
        }
        return $row;
    }

    /**
     * 卖家发货
     */
    public static function sendFreight($params,$userId){
        $order_id = array_get($params,'order_id');
        $express_company_id = array_get($params,'express_company_id');
        $express_company = $express_company_id?ExpressCompany::field('id,name,code')->where('id',$express_company_id)->find() : null;
        $order = $order_id?self::get($order_id) : null;
        if(!$order){
            throw new Exception("订单不存在");
        }
        if($order->order_type != 2){
            if(!$express_company){
                throw new Exception("物流公司不存在");
            }
            if(!$express_no= array_get($params,'express_no')){
                throw new Exception("物流单号错误");
            }
        }
        if($userId !== $order->seller_user_id){
            throw new Exception("不可操作");
        }
        if($order->state != 1){
            throw new Exception("订单不可发货");
        }
        $order->express_name = $express_company['name'];
        $order->express_company_id = $express_company['id'];
        $order->express_code = $express_company['code'];
        $order->express_no = $express_no;
        $order->freight_status = '1';
        $order->freighttime = time();
        $order->save();
        return $order;
    }

    /**
     * 卖家发货-自提地址
     */
    public static function sendAddress($params,$userId){
        $order_id = array_get($params,'order_id');
        $order = $order_id?self::get($order_id) : null;
        $address = array_get($params,'address');
        if(!$address && $order->order_type == 2){
            throw new Exception("自提地址错误");
        }
        if(!$order){
            throw new Exception("订单不存在");
        }
        if($userId !== $order->seller_user_id){
            throw new Exception("不可操作");
        }
        if($order->state != 1){
            throw new Exception("订单不可发货");
        }
        
        if($order->order_type == 2)
            $order->pick_address = $address;
        $order->freight_status = '1';
        $order->freighttime = time();
        $order->save();
        return $order;
    }


    /**
     *支付成功回调
     */
    public static function pay_notify($order_no,$transaction_id){
        $row = self::where('order_trade_no', $order_no)->find();
        if(!$row) throw new Exception("订单不存在");
        if($row['pay_status'] != '0') throw new Exception("订单已付款成功");

        db()->startTrans();
        $row->pay_status = '1';
        $row->paytime = time();
        $row->trade_no = $transaction_id;
        if($row->freight_type == 3){
            //自提直接是已发货
            $row->freight_status = 1;
            $row->freighttime = time();
        }
        $row->save();
        #商品变成已卖出
        foreach ($row->order_product as $v){
            $product = Product::where('id',$v['product_id'])->find();
            $province  = Area::getNameById($product['province_id']);
            $city  = Area::getNameById($product['city_id']);
            $region  = Area::getNameById($product['region_id']);
            // $send_user_id = $product->user_id;
            // $receive_user_id = $row->user_id;
            // $chat = new \addons\xilumarket\chatprograms\library\Chat();
            // send_to_ws($chat->say($send_user_id, [
            //     'type' => 'say',
            //     'receive_user_id' => $receive_user_id,
            //     'content'   => "你好，我的联系方式：{$product->user->username}/{$product->user->mobile}\n" . $province.$city.$region.$product['address'],
            //     'chat_type' => 1,
            //     'product_id' => $product->id,
            // ]), 'user_'.$receive_user_id);
            $row->pick_address = $province.$city.$region.$product['address'];
            if($product->number == 1){
                $product->save(['sale_out_status'=>2]);
            }
        }
        $row->save();
        #佣金分配
        Hook::listen('xilumarket_order_freeze',$row);
        #提醒卖家
        Hook::listen('xilumarket_order_pay',$row);
        db()->commit();
        return true;
    }

    public function deliveryuser() {
        return $this->hasOne(OrderDelivery::class, 'order_id', 'id');
    }
}
